from flask import request, jsonify, g
from flask_jwt_extended import (
    create_access_token, create_refresh_token, 
    get_jwt_identity, jwt_required
)
import datetime
from bson import ObjectId
import logging

from app.api.v1 import api_bp
from app import mongo
from app.utils.auth import hash_password, check_password
from app.schemas.user import LoginSchema, UserSchema, PasswordChangeSchema
from app.utils.common import normalize_data, generate_id

# 配置日志
logger = logging.getLogger(__name__)

@api_bp.route('/auth/login', methods=['POST'])
def login():
    """用户登录接口"""
    # 验证请求数据
    schema = LoginSchema()
    errors = schema.validate(request.json)
    if errors:
        return jsonify({
            'success': False,
            'message': '请求数据验证失败',
            'errors': errors
        }), 400
    
    data = request.json
    username = data.get('username')
    password = data.get('password')
    
    # 查询用户
    user = mongo.db.users.find_one({'username': username})
    if not user:
        return jsonify({
            'success': False,
            'message': '用户名或密码错误'
        }), 401
    
    # 验证密码
    if not check_password(password, user['password']):
        return jsonify({
            'success': False,
            'message': '用户名或密码错误'
        }), 401
    
    # 检查用户状态
    if user.get('status') == 'inactive':
        return jsonify({
            'success': False,
            'message': '账号已禁用，请联系管理员'
        }), 403
    
    # 生成令牌
    access_token = create_access_token(identity=str(user['_id']))
    refresh_token = create_refresh_token(identity=str(user['_id']))
    
    # 更新最后登录时间
    mongo.db.users.update_one(
        {'_id': user['_id']},
        {'$set': {'lastLogin': datetime.datetime.utcnow()}}
    )
    
    # 获取用户角色信息，用于前端权限控制
    role_info = None
    if 'role' in user:
        role = user['role']
        role_doc = mongo.db.roles.find_one({'name': role})
        if role_doc:
            role_info = {
                'name': role_doc['name'],
                'displayName': role_doc.get('displayName', role),
                'permissions': role_doc.get('permissions', [])
            }
    
    # 获取用户部门信息
    department_info = None
    if 'departmentId' in user and user['departmentId']:
        dept_id = user['departmentId']
        if isinstance(dept_id, str) and ObjectId.is_valid(dept_id):
            dept_id = ObjectId(dept_id)
        department = mongo.db.departments.find_one({'_id': dept_id})
        if department:
            department_info = {
                'id': str(department['_id']),
                'name': department.get('name', ''),
                'description': department.get('description', '')
            }
    
    return jsonify({
        'success': True,
        'message': '登录成功',
        'data': {
            'accessToken': access_token,
            'refreshToken': refresh_token,
            'user': {
                'id': str(user['_id']),
                'username': user['username'],
                'name': user.get('name', ''),
                'role': user.get('role', ''),
                'departmentId': str(user['departmentId']) if 'departmentId' in user and user['departmentId'] else None,
                'departmentInfo': department_info,
                'roleInfo': role_info
            }
        }
    }), 200

@api_bp.route('/auth/refresh', methods=['POST'])
@jwt_required(refresh=True)
def refresh():
    """刷新访问令牌"""
    current_user_id = get_jwt_identity()
    
    # 查询用户是否存在
    user = mongo.db.users.find_one({'_id': ObjectId(current_user_id)})
    if not user:
        return jsonify({
            'success': False,
            'message': '用户不存在'
        }), 401
    
    # 检查用户状态
    if user.get('status') == 'inactive':
        return jsonify({
            'success': False,
            'message': '账号已禁用，请联系管理员'
        }), 403
    
    # 生成新的访问令牌
    access_token = create_access_token(identity=current_user_id)
    
    return jsonify({
        'success': True,
        'message': '令牌刷新成功',
        'data': {
            'accessToken': access_token
        }
    }), 200

@api_bp.route('/auth/register', methods=['POST'])
def register():
    """用户注册接口"""
    # 验证请求数据
    schema = UserSchema()
    errors = schema.validate(request.json)
    if errors:
        logger.warning(f"用户注册数据验证失败: {errors}")
        return jsonify({
            'success': False,
            'message': '请求数据验证失败',
            'errors': errors
        }), 400
    
    data = request.json
    
    # 安全限制：只允许注册患者角色
    if data.get('role') != 'patient':
        logger.warning(f"尝试注册非患者角色被拒绝: {data.get('role')}, 用户名: {data.get('username')}")
        return jsonify({
            'success': False,
            'message': '公开注册仅支持患者(patient)角色',
            'error': '无权限创建其他类型的账号'
        }), 403
    
    # 检查用户名是否已存在
    if mongo.db.users.find_one({'username': data['username']}):
        return jsonify({
            'success': False,
            'message': '用户名已存在'
        }), 400
    
    # 检查邮箱是否已存在
    if mongo.db.users.find_one({'email': data['email']}):
        return jsonify({
            'success': False,
            'message': '邮箱已存在'
        }), 400
    
    # 如果有staffId，检查是否已存在
    if 'staffId' in data and data['staffId']:
        if mongo.db.users.find_one({'staffId': data['staffId']}):
            return jsonify({
                'success': False,
                'message': '工号已存在'
            }), 400
    else:
        # 如果没有提供staffId，生成一个
        role_prefix = {
            'admin': 'A',
            'doctor': 'D',
            'nurse': 'N',
            'pharmacist': 'P',
            'patient': 'PT'
        }.get(data['role'], 'U')
        data['staffId'] = generate_id(role_prefix)
    
    # 对密码进行哈希处理
    data['password'] = hash_password(data['password'])
    
    # 添加创建时间和更新时间
    now = datetime.datetime.utcnow()
    data['createdAt'] = now
    data['updatedAt'] = now
    data['lastLogin'] = None
    
    # 保存到数据库
    result = mongo.db.users.insert_one(data)
    
    # 同时创建患者档案
    if data['role'] == 'patient':
        # 准备患者基本数据
        patient_data = {
            'userId': str(result.inserted_id),
            'name': data['name'],
            'patientId': generate_id('P'),
            'gender': data.get('personalInfo', {}).get('gender', '未知'),
            'contactInfo': {
                'phone': data.get('phone', ''),
                'email': data.get('email', ''),
                'address': '',
                'emergencyContact': {
                    'name': '',
                    'phone': '',
                    'relationship': ''
                }
            },
            'registrationDate': now,
            'activeStatus': True,
            'createdAt': now,
            'updatedAt': now
        }
        
        # 为必填字段提供默认值
        # 身份证号和出生日期为必填，但用户注册时可能没提供，先给默认值后续完善
        current_year = datetime.datetime.now().year
        patient_data['birthDate'] = datetime.datetime(current_year-30, 1, 1)  # 默认30岁
        patient_data['idNumber'] = 'PENDING-' + str(result.inserted_id)[-10:]  # 临时ID号
        
        # 创建患者记录
        mongo.db.patients.insert_one(patient_data)
        
        logger.info(f"患者注册成功: 用户ID={result.inserted_id}, 用户名={data['username']}, 患者ID={patient_data['patientId']}")
    else:
        logger.info(f"用户注册成功: 用户ID={result.inserted_id}, 用户名={data['username']}")
    
    return jsonify({
        'success': True,
        'message': '用户注册成功',
        'data': {
            'id': str(result.inserted_id),
            'username': data['username'],
            'name': data['name'],
            'role': data['role'],
            'createdAt': now.isoformat()
        }
    }), 201

@api_bp.route('/auth/change-password', methods=['POST'])
@jwt_required()
def auth_change_password():
    """修改密码"""
    # 验证请求数据
    schema = PasswordChangeSchema()
    errors = schema.validate(request.json)
    if errors:
        return jsonify({
            'success': False,
            'message': '请求数据验证失败',
            'errors': errors
        }), 400
    
    data = request.json
    current_user_id = get_jwt_identity()
    
    # 查询用户
    user = mongo.db.users.find_one({'_id': ObjectId(current_user_id)})
    if not user:
        return jsonify({
            'success': False,
            'message': '用户不存在'
        }), 404
    
    # 验证当前密码
    if not check_password(data['oldPassword'], user['password']):
        return jsonify({
            'success': False,
            'message': '当前密码不正确'
        }), 400
    
    # 更新密码
    updated_password = hash_password(data['newPassword'])
    result = mongo.db.users.update_one(
        {'_id': ObjectId(current_user_id)},
        {
            '$set': {
                'password': updated_password,
                'updatedAt': datetime.datetime.utcnow()
            }
        }
    )
    
    if result.modified_count == 0:
        return jsonify({
            'success': False,
            'message': '密码修改失败'
        }), 500
    
    return jsonify({
        'success': True,
        'message': '密码修改成功',
        'data': {
            'updatedAt': datetime.datetime.utcnow().isoformat()
        }
    }), 200

@api_bp.route('/auth/me', methods=['GET'])
@jwt_required()
def get_me():
    """获取当前登录用户信息"""
    current_user_id = get_jwt_identity()
    
    # 查询用户
    user = mongo.db.users.find_one({'_id': ObjectId(current_user_id)})
    if not user:
        return jsonify({
            'success': False,
            'message': '用户不存在'
        }), 404
    
    # 获取用户角色信息
    role_info = None
    if 'role' in user:
        role = user['role']
        role_doc = mongo.db.roles.find_one({'name': role})
        if role_doc:
            role_info = {
                'name': role_doc['name'],
                'displayName': role_doc.get('displayName', role),
                'permissions': role_doc.get('permissions', [])
            }
    
    # 获取用户部门信息
    department_info = None
    if 'departmentId' in user and user['departmentId']:
        dept_id = user['departmentId']
        if isinstance(dept_id, str) and ObjectId.is_valid(dept_id):
            dept_id = ObjectId(dept_id)
        department = mongo.db.departments.find_one({'_id': dept_id})
        if department:
            department_info = {
                'id': str(department['_id']),
                'name': department.get('name', ''),
                'description': department.get('description', '')
            }
    
    # 移除敏感信息
    user.pop('password', None)
    
    # 标准化数据
    normalized_user = normalize_data(user)
    
    return jsonify({
        'success': True,
        'data': {
            'user': normalized_user,
            'departmentInfo': department_info,
            'roleInfo': role_info
        }
    }), 200 